import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.fastjson.JSONObject;
import gudusoft.gsqlparser.EDbVendor;
import gudusoft.gsqlparser.TGSqlParser;
import gudusoft.gsqlparser.TStatementList;
import gudusoft.gsqlparser.nodes.TResultColumn;
import gudusoft.gsqlparser.nodes.TTable;
import gudusoft.gsqlparser.stmt.TSelectSqlStatement;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Tgsparser_1 {
    static class Node{
        public List<Col> cols = new ArrayList<>();
        public List<Tab> tabs = new ArrayList<>();
        private Node(){};

        public Node(List<Col> cols, List<Tab> tabs) {
            this.cols = cols;
            this.tabs = tabs;
            assert !this.cols.isEmpty();
            assert !this.tabs.isEmpty();
            Map<String, Tab> tabMap = tabs.stream().collect(Collectors.toMap(s -> s.getName(), s -> s));
            for (Col col : this.cols) {
                if(this.tabs.size() == 1){
                    col.at_table = this.tabs.get(0);
                    col.at_table_name = this.tabs.get(0).name;
                }else if(col.at_table_name.isEmpty()){
                    ArrayList<Col> cols1 = new ArrayList<>();
                    for (Tab tab : this.tabs) {
                        cols1.addAll(tab.getNode().cols);
                    }
                    List<Col> collect = cols1.stream().filter(x -> {
                        return  x.name.equalsIgnoreCase(col.name);
                    }).collect(Collectors.toList());
                    if(collect.size() > 1){
                        throw new RuntimeException(String.format(" Column '%s' in field list is ambiguous",col.name));
                    }
                    col.pre_col = collect.get(0);
                    col.at_table = collect.get(0).at_table;
                    col.at_table_name = collect.get(0).at_table.name;
                }else {
                    Tab tab = tabMap.get(col.at_table_name);
                    col.at_table = tab;
                    if(col.at_table.isButtom){
                        col.pre_col = null;
                    }else {
                        for (Col col1 : col.at_table.node.cols) {
                            if(col1.name.equalsIgnoreCase(col.name)){
                                col.pre_col = col1;
                                break;
                            }
                        }
                    }
                }

            }
        }
    }
    static class Col{
        public String origin_name;
        public String name;
        public String at_table_name;
        public Tab at_table;
        public Col pre_col;
    }
    static class Tab{
        public String name;
        public boolean isButtom = true;
        public Node node;
        public String getName() {
            return name;
        }
        public Node getNode() {
            return node;
        }

    }

    public static void main(String[] args) {
        parseTred();
    }
    public static void parseTred(){
        TGSqlParser sqlparser = new TGSqlParser(EDbVendor.dbvmysql);
        sqlparser.sqltext = "SELECT `user`.name , `order`.price " +
                "               FROM   `user`  " +
                "                left join (select c1 as price from test1) as `order` on user.id=order.id " +
                "            WHERE  `user`.id = `order`.uid";
        System.out.println(SQLUtils.format(sqlparser.sqltext, JdbcConstants.MYSQL));
        System.out.println("------------------");
        int ret = sqlparser.parse();
        Node root = null;
        if (ret == 0) {
            TStatementList stmts = sqlparser.getSqlstatements();
            TSelectSqlStatement stmt = (TSelectSqlStatement) stmts.get(0);

            // getResultColumn 获取 select 语句形成的 record set 中的 column
            List<Col> cols = getColList(stmt);
            List<Tab> tabs = getTabList(stmt);
            root = new Node(cols,tabs);
        } else {
            System.out.println(sqlparser.getErrormessage());
        }
        System.out.println(JSONObject.toJSON(root).toString());
    }

    private static List<Tab> getTabList(TSelectSqlStatement stmt) {
        List<Tab> tabs = new ArrayList<>();
        for (TTable table : stmt.tables) {
            Tab tab = new Tab();
            if(table.getTableType().name().equalsIgnoreCase("subquery")){
                tab.name = table.getAliasName();
            }else {
                tab.name = table.getTableName().toString();
            }
            TSelectSqlStatement subquery = table.subquery;
            if(subquery != null){
                tab.isButtom = false;
                tab.node = new Node(getColList(subquery), getTabList(subquery));;
            }else {
                tab.isButtom = true;
            }
            tabs.add(tab);
        }
        return tabs;
    }

    private static List<Col> getColList(TSelectSqlStatement stmt) {
        List<Col> cols = new ArrayList<>();
        for (TResultColumn column : stmt.getResultColumnList()) {
            Col col = new Col();
            col.origin_name = column.getAliasClause()!=null?column.getStartToken().toString():column.getDisplayName().toString();
            col.name = column.getAliasClause() == null?column.getDisplayName():column.getAliasClause().toString();
            col.at_table_name = column.getPrefixTable();
            cols.add(col);
        }
        return cols;
    }

    /*public static void main(String[] args) {



        TGSqlParser sqlparser = new TGSqlParser(EDbVendor.dbvmysql);
//        sqlparser.sqltext = "SELECT `user`.name," +
//                "           `order`.price       " +
//                "               FROM   `user`,  " +
//                "                       `order` " +
//                "            WHERE  `user`.id = `order`.uid";
        sqlparser.sqltext = "SELECT `user`.name , `order`.price " +
                "               FROM   `user`  " +
                "                left join (select c1 as price from test1) as `order` on user.id=order.id " +
                "            WHERE  `user`.id = `order`.uid";
        System.out.println(SQLUtils.format(sqlparser.sqltext, JdbcConstants.MYSQL));
        System.out.println("------------------");
        int ret = sqlparser.parse();
        if (ret == 0) {
            TStatementList stmts = sqlparser.getSqlstatements();
            TSelectSqlStatement stmt = (TSelectSqlStatement) stmts.get(0);

            // getResultColumn 获取 select 语句形成的 record set 中的 column
            stmt.getResultColumnList().forEach(column -> {
                System.out.printf("%s(%s) -> %s(RS-1)\n",
                        column.getDisplayName(),
                        column.getPrefixTable(),
                        column.getDisplayName()
                );

            });
            for (TTable table : stmt.tables) {
                System.out.println(table.getTableName());
                TSelectSqlStatement subquery = table.subquery;
                if(subquery != null){
                    subquery.getResultColumnList().forEach(column -> {
                        System.out.printf("%s(%s) -> %s(RS-1)\n",
                                column.getDisplayName(),
                                column.getPrefixTable(),
                                column.getDisplayName()
                        );

                    });
                    for (TTable tTable : subquery.tables) {
                        System.out.println(tTable);
                    }
                }
            }
        } else {
            System.out.println(sqlparser.getErrormessage());
        }

    }*/
}
